﻿using System;
using System.IO;
using Aliyun.OSS;
using Aliyun.OSS.Common;

namespace alioss
{
    class Program
    {
        static void Main(string[] args)
        {
            // 配置信息
            string accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID") ?? "您的 AccessKey ID"; // 替换为您的 AccessKey ID
            string accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET") ?? "您的 AccessKey Secret"; // 替换为您的 AccessKey Secret
            string endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 替换为您的 OSS Endpoint
            string bucketName = "您的 Bucket 名称"; // 替换为您的 Bucket 名称
            string localDir = "/app/oss"; // 本地保存目录，确保存在且可写 Windows下用 @"D:\oss\"
            string prefix = ""; // 可选，指定前缀（如 "testfolder/"）以下载特定文件夹

            Console.WriteLine($"accessKeyId:{accessKeyId}   accessKeySecret:{accessKeySecret}");
            Console.WriteLine($"endpoint:{endpoint}");
            Console.WriteLine($"bucketName:{bucketName}");
            Console.WriteLine($"localDir:{localDir}");

            try
            {
                // 初始化 OSS 客户端
                var client = new OssClient(endpoint, accessKeyId, accessKeySecret);

                // 确保本地目录存在
                if (!Directory.Exists(localDir))
                {
                    Directory.CreateDirectory(localDir);
                }

                // 分页列出所有对象
                string nextMarker = null;
                bool isTruncated = true;
                DateTime dtbegin = DateTime.Now;
                long total = 0;
                while (isTruncated)
                {
                    var listObjectsRequest = new ListObjectsRequest(bucketName)
                    {
                        Prefix = prefix,
                        MaxKeys = 1000, // 每次最多列出 1000 个对象
                        Marker = nextMarker
                    };

                    var result = client.ListObjects(listObjectsRequest);
                    foreach (var obj in result.ObjectSummaries)
                    {
                        // 跳过空文件夹（以 / 结尾的对象）
                        if (obj.Key.EndsWith("/"))
                        {
                            continue;
                        }

                        // 构造本地文件路径，保留 OSS 目录结构
                        string localFile = Path.Combine(localDir, obj.Key);
                        string localFileDir = Path.GetDirectoryName(localFile);

                        // 确保本地目录存在
                        if (!Directory.Exists(localFileDir))
                        {
                            Directory.CreateDirectory(localFileDir);
                        }

                        // 下载文件
                        Console.WriteLine($"正在下载: {obj.Key} 到 {localFile}");
                        var getObjectRequest = new GetObjectRequest(bucketName, obj.Key);
                        using (var resultStream = client.GetObject(getObjectRequest))
                        {
                            using (var fs = File.OpenWrite(localFile))
                            {
                                resultStream.Content.CopyTo(fs);
                                total++;
                            }
                        }
                    }

                    // 检查是否还有更多对象
                    nextMarker = result.NextMarker;
                    isTruncated = result.IsTruncated;
                }

                Console.WriteLine($"所有文件下载完成[ {total} 个文件]！{GetTimeSpan(dtbegin)}");
            }
            catch (OssException ex)
            {
                Console.WriteLine($"下载失败: OSS错误 - {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"下载失败: {ex.Message}");
            }
        }
        /// <summary>
        /// 获取耗时
        /// </summary>
        /// <param name="btime">开始时间</param>
        /// <param name="etime">结束时间 默认当前</param>
        /// <returns></returns>
        public static string GetTimeSpan(DateTime btime, DateTime? etime = null)
        {
            if (etime == null) etime = DateTime.Now;
            TimeSpan ts = etime.Value.Subtract(btime);
            var hs = $"耗时{(ts.Days == 0 ? "" : (ts.Days + "天 "))}{(ts.Hours == 0 ? "" : (ts.Hours + "小时 "))} {(ts.Minutes == 0 ? "" : (ts.Minutes + "分钟 "))} {(ts.Seconds == 0 ? "" : (ts.Seconds + "秒 "))} {ts.Milliseconds}毫秒 [{ts.TotalMilliseconds}ms]";
            return hs;
        }
    }
}
